home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / MKMAZE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  11KB  |  456 lines

  1. /*    SCCS Id: @(#)mkmaze.c    3.0    88/10/25
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. extern int x_maze_max, y_maze_max;
  8.  
  9. #if defined(WALLIFIED_MAZE) || defined(STRONGHOLD)
  10. static int FDECL(iswall,(int,int));
  11. static boolean FDECL(okay,(int,int,int));
  12. static void FDECL(maze0xy,(coord *));
  13.  
  14. static int
  15. iswall(x,y)
  16. int x,y;
  17. {
  18. # ifndef WALLIFIED_MAZE
  19.     if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1)
  20. # else
  21.     if (x<0 || y<0 || x>COLNO || y>ROWNO)
  22. # endif
  23.         return 0;
  24.     return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)
  25.         || levl[x][y].typ == SDOOR);
  26. }
  27.  
  28. void
  29. wallification(x1, y1, x2, y2, see)
  30. int x1, y1, x2, y2;
  31. boolean see;
  32. {
  33.     uchar type;
  34.     short x,y;
  35.     register struct rm *room;
  36.  
  37.     if (x1 < 0) x1 = 0;
  38.     if (x2 < x1) x2 = x1;
  39.     if (x2 > COLNO-1) x2 = COLNO-1;
  40.     if (x1 > x2) x1 = x2;
  41.     if (y1 < 0) y1 = 0;
  42.     if (y2 < y1) y2 = y1;
  43.     if (y2 > COLNO-1) y2 = ROWNO-1;
  44.     if (y1 > y2) y1 = y2;
  45.     for(x = x1; x <= x2; x++)
  46.         for(y = y1; y <= y2; y++) {
  47.         room = &levl[x][y];
  48.         type = room->typ;
  49.         if (iswall(x,y)) {
  50.           if (IS_DOOR(type))
  51.             continue;
  52.           else
  53.             if (iswall(x,y-1))
  54.             if (iswall(x,y+1))
  55.                 if (iswall(x-1,y))
  56.                 if (iswall(x+1,y))
  57.                     room->typ = CROSSWALL;
  58.                 else
  59.                     room->typ = TLWALL;
  60.                 else
  61.                 if (iswall(x+1,y))
  62.                     room->typ = TRWALL;
  63.                 else
  64.                     room->typ = VWALL;
  65.             else
  66.                 if (iswall(x-1,y))
  67.                 if (iswall(x+1,y))
  68.                     room->typ = TUWALL;
  69.                 else
  70.                     room->typ = BRCORNER;
  71.                 else
  72.                 if (iswall(x+1,y))
  73.                     room->typ = BLCORNER;
  74.                 else
  75.                     room->typ = VWALL;
  76.             else
  77.             if (iswall(x,y+1))
  78.                 if (iswall(x-1,y))
  79.                 if (iswall(x+1,y))
  80.                     room->typ = TDWALL;
  81.                 else
  82.                     room->typ = TRCORNER;
  83.                 else
  84.                 if (iswall(x+1,y))
  85.                     room->typ = TLCORNER;
  86.                 else
  87.                     room->typ = VWALL;
  88.             else
  89.                 room->typ = HWALL;
  90.             if (type == SDOOR) room->typ = type;
  91.         }
  92.         room->scrsym = news0(x,y);
  93.         if (see) room->seen = 0;
  94.         }
  95. }
  96. #endif /* WALLIFIED_MAZE /**/
  97.  
  98. static boolean
  99. okay(x,y,dir)
  100. int x,y;
  101. register int dir;
  102. {
  103.     move(&x,&y,dir);
  104.     move(&x,&y,dir);
  105.     if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0)
  106.         return(FALSE);
  107.     return(TRUE);
  108. }
  109.  
  110. static void
  111. maze0xy(cc)    /* find random starting point for maze generation */
  112.     coord    *cc;
  113. {
  114.     cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
  115.     cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
  116.     return;
  117. }
  118.  
  119. /* NCR towers define "tower".  Blecccch. */
  120. #ifdef tower
  121. #  undef tower
  122. #endif
  123.  
  124. static const uchar NEARDATA tower[] = {
  125.     MOAT,      MOAT,     MOAT,     MOAT,    MOAT,      MOAT,     MOAT,
  126.     MOAT,      MOAT,     TLCORNER, HWALL,    TRCORNER, MOAT,     MOAT,
  127.     MOAT,      TLCORNER, BRCORNER, ROOM,    BLCORNER, TRCORNER, MOAT,
  128.     MOAT,      VWALL,    ROOM,     ROOM,    ROOM,      VWALL,    MOAT,
  129.     MOAT,      BLCORNER, TRCORNER, ROOM,    TLCORNER, BRCORNER, MOAT,
  130.     MOAT,      MOAT,     BLCORNER, HWALL,    BRCORNER, MOAT,     MOAT,
  131.     MOAT,      MOAT,     MOAT,     MOAT,    MOAT,      MOAT,     MOAT,
  132. };
  133.  
  134. void
  135. makemaz()
  136. {
  137.     int x,y;
  138.     register int zx,zy;
  139.     coord mm;
  140.     int i;
  141.  
  142.     is_maze_lev = TRUE;
  143. #ifdef STRONGHOLD
  144.     xdnladder = ydnladder = xupladder = yupladder = 0;
  145.     if (dlevel == stronghold_level) {
  146.         if (load_special("castle")) {
  147.             xupstair = yupstair = 3;
  148.             levl[xupstair][yupstair].scrsym = UP_SYM;
  149.             levl[xupstair][yupstair].typ = STAIRS;
  150.             return;
  151.         }
  152.         impossible("Cannot build the STRONGHOLD!");
  153.     }
  154.     if (dlevel == tower_level) {
  155.         if (load_special("tower1")) {
  156.             xupstair = yupstair = 3;
  157.             levl[xupstair][yupstair].scrsym = UP_SYM;
  158.             levl[xupstair][yupstair].typ = STAIRS;
  159.             return;
  160.         }
  161.         impossible("Cannot build the TOWER!");
  162.     }
  163.     if (dlevel == tower_level+1) {
  164.         if (load_special("tower2")) {
  165.             xupstair = yupstair = 3;
  166.             levl[xupstair][yupstair].scrsym = UP_SYM;
  167.             levl[xupstair][yupstair].typ = STAIRS;
  168.             return;
  169.         }
  170.         impossible("Cannot build the TOWER!");
  171.     }
  172.     if (dlevel == tower_level+2) {
  173.         if (load_special("tower3")) {
  174.             xupstair = yupstair = 3;
  175.             levl[xupstair][yupstair].scrsym = UP_SYM;
  176.             levl[xupstair][yupstair].typ = STAIRS;
  177.             return;
  178.         }
  179.         impossible("Cannot build the TOWER!");
  180.     }
  181. # ifdef ENDGAME
  182.     if (dlevel == ENDLEVEL) {    /* EndGame level */
  183.         if (load_special("endgame")) {
  184.             pline("Well done, mortal!");
  185.             pline("But now thou must face the final Test...");
  186.             pline("Prove thyself worthy or perish!");
  187.             u.ux = x_maze_max - 1;
  188.             u.uy = y_maze_max - 1;
  189.             xupstair = yupstair = 0;
  190.             return;
  191.         }
  192.         impossible("Cannot build the EndGame Level!");
  193.         done(ESCAPED);
  194.     }
  195. # endif
  196. #endif
  197. #ifndef WALLIFIED_MAZE
  198.     for(x = 2; x < x_maze_max; x++)
  199.         for(y = 2; y < y_maze_max; y++)
  200.             levl[x][y].typ = STONE;
  201. #else
  202.     for(x = 2; x <= x_maze_max; x++)
  203.         for(y = 2; y <= y_maze_max; y++)
  204.             levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
  205. #endif
  206.  
  207.     /* make decoy wizard levels */
  208.     if((dlevel == wiz_level) ||
  209. #ifdef STRONGHOLD
  210.        (!rn2(3) && (dlevel > stronghold_level+1))) {
  211. #else
  212.        (!rn2(3) && (dlevel > medusa_level+1))) {
  213. #endif
  214.  
  215.         register struct monst *mtmp;
  216.  
  217.         zx = x_maze_max / 2;
  218.         zy = y_maze_max / 2;
  219.         if (!(zx % 2)) zx++;
  220.         if (!(zy % 2)) zy++;
  221.         for(y = zy-3, i=0; y <= zy+3; y++)
  222.         for(x = zx-3; x <= zx+3; x++)
  223.             levl[x][y].typ = tower[i++];
  224.         walkfrom(zx+4, zy);
  225.         if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy))
  226.         mtmp->msleep = 1;
  227.         (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2);
  228.         if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy))
  229.         mtmp->msleep = 1;
  230.         if (dlevel == wiz_level) {
  231.  
  232.         (void) mksobj_at(AMULET_OF_YENDOR, zx, zy);
  233.         flags.made_amulet = 1;
  234.         if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy))
  235.             mtmp->msleep = 1;
  236.         } else {
  237.         struct obj *ot;
  238.             /* make a cheap plastic imitation */
  239.         if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy))
  240.             ot-> spe = -1;
  241.         (void) makemon(&mons[dprince()], zx, zy);
  242.         }
  243.         /* they should wake up when we intrude */
  244.         (void) maketrap(zx-1, zy, SQBRD);
  245.         (void) maketrap(zx+1, zy, SQBRD);
  246.         (void) maketrap(zx, zy-1, SQBRD);
  247.         (void) maketrap(zx, zy+1, SQBRD);
  248.     } else {
  249.         maze0xy(&mm);
  250.         zx = mm.x;
  251.         zy = mm.y;
  252.         walkfrom(zx,zy);
  253. #ifndef STRONGHOLD    /* it's in the castle */
  254. # ifdef HARD        /* only one wand of wishing created */
  255.         if(!rn2(10) || (dlevel == medusa_level + 1))
  256. # endif
  257.         (void) mksobj_at(WAN_WISHING, zx, zy);
  258. #endif
  259.         (void) mksobj_at(BOULDER, zx, zy);  /* put a boulder on top of it */
  260.     }
  261.  
  262. #ifdef WALLIFIED_MAZE
  263.     wallification(2, 2, x_maze_max, y_maze_max, TRUE);
  264. #else
  265.     for(x = 2; x < x_maze_max; x++)
  266.         for(y = 2; y < y_maze_max; y++)
  267.             levl[x][y].scrsym = news0(x,y);
  268. #endif
  269.     mazexy(&mm);
  270.     levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM;
  271.     levl[xupstair][yupstair].typ = STAIRS;
  272.     xdnstair = ydnstair = 0;
  273. #ifdef STRONGHOLD
  274.     if (dlevel < stronghold_level) {
  275.         mazexy(&mm);
  276.         levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM;
  277.         levl[xdnstair][ydnstair].typ = STAIRS;
  278.     }
  279. #endif
  280.     for(x = rn1(8,11); x; x--) {
  281.         mazexy(&mm);
  282.         (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y, TRUE);
  283.     }
  284.     for(x = rn1(10,2); x; x--) {
  285.         mazexy(&mm);
  286.         (void) mksobj_at(BOULDER, mm.x, mm.y);
  287.     }
  288.     mazexy(&mm);
  289.     (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
  290.     for(x = rn1(5,7); x; x--) {
  291.         mazexy(&mm);
  292.         (void) makemon((struct permonst *) 0, mm.x, mm.y);
  293.     }
  294.     for(x = rn1(6,7); x; x--) {
  295.         mazexy(&mm);
  296.         mkgold(0L,mm.x,mm.y);
  297.     }
  298.     for(x = rn1(6,7); x; x--)
  299.         mktrap(0,1,(struct mkroom *) 0);
  300. }
  301.  
  302. #ifdef MSDOS
  303. /* Make the mazewalk iterative by faking a stack.  This is needed to
  304.  * ensure the mazewalk is successful in the limited stack space of
  305.  * the program.  This iterative version uses the mimumum amount of stack
  306.  * that is totally safe.
  307.  */
  308. void
  309. walkfrom(x,y)
  310. int x,y;
  311. {
  312. #define CELLS (ROWNO * COLNO) / 4        /* a maze cell is 4 squares */
  313.     char mazex[CELLS + 1], mazey[CELLS + 1];    /* char's are OK */
  314.     int q, a, dir, pos;
  315.     int dirs[4];
  316.  
  317.     pos = 1;
  318.     mazex[pos] = (char) x;
  319.     mazey[pos] = (char) y;
  320.     while (pos) {
  321.         x = (int) mazex[pos];
  322.         y = (int) mazey[pos];
  323. #ifndef WALLIFIED_MAZE
  324.         levl[x][y].typ = CORR;
  325. #else
  326.         levl[x][y].typ = ROOM;
  327. #endif
  328.         q = 0;
  329.         for (a = 0; a < 4; a++)
  330.             if(okay(x, y, a)) dirs[q++]= a;
  331.         if (!q)
  332.             pos--;
  333.         else {
  334.             dir = dirs[rn2(q)];
  335.             move(&x, &y, dir);
  336. #ifndef WALLIFIED_MAZE
  337.             levl[x][y].typ = CORR;
  338. #else
  339.             levl[x][y].typ = ROOM;
  340. #endif
  341.             move(&x, &y, dir);
  342.             pos++;
  343.             if (pos > CELLS)
  344.                 panic("Overflow in walkfrom");
  345.             mazex[pos] = (char) x;
  346.             mazey[pos] = (char) y;
  347.         }
  348.     }
  349. }
  350. #else
  351.  
  352. void
  353. walkfrom(x,y) int x,y; {
  354. register int q,a,dir;
  355. int dirs[4];
  356. #ifndef WALLIFIED_MAZE
  357.     levl[x][y].typ = CORR;
  358. #else
  359.     levl[x][y].typ = ROOM;
  360. #endif
  361.     while(1) {
  362.         q = 0;
  363.         for(a = 0; a < 4; a++)
  364.             if(okay(x,y,a)) dirs[q++]= a;
  365.         if(!q) return;
  366.         dir = dirs[rn2(q)];
  367.         move(&x,&y,dir);
  368. #ifndef WALLIFIED_MAZE
  369.         levl[x][y].typ = CORR;
  370. #else
  371.         levl[x][y].typ = ROOM;
  372. #endif
  373.         move(&x,&y,dir);
  374.         walkfrom(x,y);
  375.     }
  376. }
  377. #endif /* MSDOS */
  378.  
  379. void
  380. move(x,y,dir)
  381. register int *x, *y;
  382. register int dir;
  383. {
  384.     switch(dir){
  385.         case 0: --(*y); break;
  386.         case 1: (*x)++; break;
  387.         case 2: (*y)++; break;
  388.         case 3: --(*x); break;
  389.     }
  390. }
  391.  
  392. void
  393. mazexy(cc)    /* find random point in generated corridors,
  394.            so we don't create items in moats, bunkers, or walls */
  395.     coord    *cc;
  396. {
  397.     int cpt=0;
  398.  
  399.     do {
  400.         cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
  401.         cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
  402.         cpt++;
  403. #ifndef WALLIFIED_MAZE
  404.     } while (cpt < 100 && levl[cc->x][cc->y].typ != CORR);
  405. #else
  406.     } while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM);
  407. #endif
  408.     if (cpt >= 100) panic("mazexy: can't find a place!");
  409.     return;
  410. }
  411.  
  412. void
  413. bound_digging()
  414. /* put a non-diggable boundary around the initial portion of a level map.
  415.  * assumes that no level will initially put things beyond the isok() range.
  416.  */
  417. {
  418.     register int x,y;
  419.     register boolean found;
  420.     int xmin,xmax,ymin,ymax;
  421.  
  422.     found = FALSE;
  423.     for(xmin=1; !found; xmin++)
  424.         for(y=0; y<=ROWNO-1; y++)
  425.             if(levl[xmin][y].typ != STONE) found = TRUE;
  426.     xmin -= 2;
  427.  
  428.     found = FALSE;
  429.     for(xmax=COLNO-2; !found; xmax--)
  430.         for(y=0; y<=ROWNO-1; y++)
  431.             if(levl[xmax][y].typ != STONE) found = TRUE;
  432.     xmax += 2;
  433.  
  434.     found = FALSE;
  435.     for(ymin=1; !found; ymin++)
  436.         for(x=xmin; x<=xmax; x++)
  437.             if(levl[x][ymin].typ != STONE) found = TRUE;
  438.     ymin -= 2;
  439.  
  440.     found = FALSE;
  441.     for(ymax=ROWNO-2; !found; ymax--)
  442.         for(x=xmin; x<=xmax; x++)
  443.             if(levl[x][ymax].typ != STONE) found = TRUE;
  444.     ymax += 2;
  445.  
  446.     for(x=xmin; x<=xmax; x++) {
  447.         levl[x][ymin].diggable = W_NONDIGGABLE;
  448.         levl[x][ymax].diggable = W_NONDIGGABLE;
  449.     }
  450.  
  451.     for(y=ymin; y<=ymax; y++) {
  452.         levl[xmin][y].diggable = W_NONDIGGABLE;
  453.         levl[xmax][y].diggable = W_NONDIGGABLE;
  454.     }
  455. }
  456.